package cn.easyutil.util.javaUtil;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;

/**
 * 上传工具
 * 
 * @author spc
 *
 */
public class UploadUtil {

	/** 单例链接 */
	private volatile OSSClient ossClient;
	/** oss-cdn域名 */
	private String endPoint;
	private String bucketName;
	private String accessKeyId;
	private String accessKeySecret;

	public UploadUtil() {
	}

	/**
	 * 图片上传(校验是否图片类型)
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名称
	 * @param useOSS
	 *            是否使用oss false:本地存储
	 * @return
	 */
	public String pictureUpload(InputStream input, String fileFullName, boolean useOSS) {
		byte[] but = IOUtil.inputToByte(input);
		if (!FileUtil.isPicture(but)) {
			LoggerUtil.error(this.getClass(), "上传文件非图片类型");
			throw new RuntimeException("file not picture type");
		}
		return upload(IOUtil.byteToInput(but),fileFullName);
	}

	/**
	 * 视频上传(校验是否视频类型)
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名称
	 * @param useOSS
	 *            是否使用oss false:本地存储
	 * @return
	 */
	public String videoUpload(InputStream input, String fileFullName, boolean useOSS) {
		byte[] but = IOUtil.inputToByte(input);
		if (!FileUtil.isVideo(but)) {
			LoggerUtil.error(this.getClass(), "上传文件非视频类型");
			throw new RuntimeException("file not video type");
		}
		return upload(IOUtil.byteToInput(but),fileFullName);
	}

	/**
	 * 文本上传(校验是否文本类型)
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名称
	 * @param useOSS
	 *            是否使用oss false:本地存储
	 * @return
	 */
	public String docUpload(InputStream input, String fileFullName, boolean useOSS) {
		byte[] but = IOUtil.inputToByte(input);
		if (!FileUtil.isDoc(but)) {
			LoggerUtil.error(this.getClass(), "上传文件非doc类型");
			throw new RuntimeException("file not doc type");
		}
		return upload(IOUtil.byteToInput(but),fileFullName);
	}

	/**
	 * 音频上传(校验是否音频类型)
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名称
	 * @param useOSS
	 *            是否使用oss false:本地存储
	 * @return
	 */
	public String audioUpload(InputStream input, String fileFullName, boolean useOSS) {
		byte[] but = IOUtil.inputToByte(input);
		if (!FileUtil.isAudio(but)) {
			LoggerUtil.error(this.getClass(), "上传文件非音频类型");
			throw new RuntimeException("file not audio type");
		}
		return upload(IOUtil.byteToInput(but),fileFullName, useOSS);
	}

	/**
	 * 文件上传
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名称
	 * @param useOSS
	 *            是否使用oss false:本地存储
	 * @return
	 */
	public String upload(InputStream input, String fileFullName, boolean useOSS) {
		if (useOSS) {
			return OSSUpload(input, fileFullName);
		} else {
			return localUpload(input, fileFullName);
		}
	}

	/**
	 * 文件上传
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名称
	 * @return 文件最终存放的绝对路径
	 */
	public String upload(InputStream input, String fileFullName) {
		return upload(input,fileFullName, true);
	}

	/**
	 * 初始化阿里oss参数
	 * 
	 * @param bucketName
	 * @param accessKeyId
	 * @param accessKeySecret
	 */
	public UploadUtil(String bucketName, String accessKeyId, String accessKeySecret, String endpoint) {
		this.bucketName = bucketName;
		this.accessKeyId = accessKeyId;
		this.accessKeySecret = accessKeySecret;
		this.endPoint = endpoint;
	}

	/**
	 * 文件上传
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名称
	 * @return 文件最终存放的绝对路径
	 */
	public String OSSUpload(InputStream input, String fileFullName) {
		if (this.accessKeyId == null || this.accessKeySecret == null || this.bucketName == null
				|| this.endPoint == null) {
			throw new RuntimeException("OSS param missing");
		}
//		 最终文件全路径
//		String finalPath = filePath + fileName + "." + postfix;
		OSSClient client = getClient();
		// 创建上传Object的Metadata
		ObjectMetadata metadata = new ObjectMetadata();
		int size = 0;
		try {
			size = input.available();
			metadata.setContentLength(size);
			LoggerUtil.debug(this.getClass(), "oss文件上传,文件大小:" + size + ",文件名:" + fileFullName);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		metadata.setCacheControl("no-cache");
		metadata.setHeader("Pragma", "no-cache");
		// 设置文件网络类型
		// metadata.setContentType(fileType);
		metadata.setContentDisposition("filename/filesize=" + fileFullName + "/" + size + "Byte.");
		try {
			LoggerUtil.info(this.getClass(), "oss文件上传开始");
			client.putObject(bucketName, fileFullName, input, metadata);
			LoggerUtil.debug(this.getClass(), "oss文件上传完成,路径为:" + fileFullName);
		} catch (Exception e) {
			LoggerUtil.error(this.getClass(), "oss文件上传失败:" + e.getMessage());
		}
		client.shutdown();
		return "https://"+this.bucketName+"."+this.endPoint+"/"+fileFullName;
	}

	// 初始化秘钥信息
	private OSSClient getClient() {
		if (ossClient == null) {
			synchronized (this) {
				if (ossClient == null) {
					ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
				}
			}
		}
		return ossClient;
	}

	/**
	 * 本地上传
	 * @param input	资源
	 * @param file	存放文件路径
	 * @return
	 */
	public String localUpload(InputStream input, File file) {
		FileOutputStream fout = null;
		try {
			int size = input.available();
			LoggerUtil.debug(this.getClass(),
					"本地文件存储,文件大小:" + size + ",文件名:" + file.getName() + ",文件存放路径:" + file.getAbsolutePath());
			fout = new FileOutputStream(file);
			byte[] but = new byte[1024 * 1024];
			int length = 0;
			while ((length = input.read(but)) != -1) {
				fout.write(but, 0, length);
			}
			fout.flush();
		} catch (Exception e) {
			LoggerUtil.error(this.getClass(), "本地文件存储失败:" + e.getMessage());
			throw new RuntimeException(e);
		} finally {
			try {
				fout.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		LoggerUtil.debug(this.getClass(), "本地文件存储成功,路径为:" + file.getAbsolutePath());
		return file.getAbsolutePath();
	}

	/**
	 * 文件流存放本地
	 * 
	 * @param input
	 *            文件流
	 * @param fileFullName
	 *            文件名
	 * @return 文件最终存放的绝对路径
	 */
	public String localUpload(InputStream input, String fileFullName) {
		File file = new File(fileFullName);
		return localUpload(input, file);

	}

	/**
	 * 读取本地文件并转成byte字节
	 * 
	 * @param filePath
	 * @return
	 */
	public byte[] localDown(String filePath) {
		File file = null;
		FileInputStream fin = null;
		ByteArrayOutputStream out = null;
		try {
			file = new File(filePath);
			if (!file.exists()) {
				throw new RuntimeException("file[" + filePath + "] do not exist");
			}
			out = new ByteArrayOutputStream();
			fin = new FileInputStream(file);
			byte[] but = new byte[1024 * 1024];
			int length = 0;
			while ((length = fin.read(but)) != -1) {
				out.write(but, 0, length);
			}
			return out.toByteArray();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				fin.close();
				out.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}
	
	public static void main(String[] args) throws FileNotFoundException {
		UploadUtil util = new UploadUtil("mimikko-test","LTAI4GAxWdob1nY9LTVxsjrk","yonU6NQfzrEEu5W5jiGRabiaepK3Be","oss-cn-shanghai.aliyuncs.com");
		String result = util.OSSUpload(new FileInputStream(new File("D://sign.png")), "picture/"+UUID.randomUUID().toString().replace("-", "")+".png");
		System.out.println(result);
	}
}
